package com.atguiguNIO.buffer;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.channels.FileChannel;

public class BufferDemo01 {


    private static void rwFile() {
        try {

            // 获取通道，该通道允许写操作
            FileChannel fileChannel = new FileOutputStream("data.txt").getChannel();
            // 将字节数组包装到缓冲区中
            fileChannel.write(ByteBuffer.wrap("Some text".getBytes()));
            // 关闭通道
            fileChannel.close();

            // 随机读写文件流创建的管道
            fileChannel = new RandomAccessFile("data.txt", "rw").getChannel();
            // fc.position()计算从文件的开始到当前位置之间的字节数
            System.out.println("此通道的文件位置：" + fileChannel.position());
            // 设置此通道的文件位置,fc.size()此通道的文件的当前大小,该条语句执行后，通道位置处于文件的末尾
            fileChannel.position(fileChannel.size());
            // 在文件末尾写入字节
            fileChannel.write(ByteBuffer.wrap("Some more".getBytes()));
            fileChannel.close();

            // 用通道读取文件
            fileChannel = new FileInputStream("data.txt").getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(8);
            // 将文件内容读到指定的缓冲区中
            fileChannel.read(buffer);
            buffer.flip();//此行语句一定要有
            while (buffer.hasRemaining()) {
                System.out.print((char) buffer.get());
            }
            fileChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 使用BIO读取文件
     */
    private static void bioReadFile() {

        File file = new File("test.txt");
        long startTime = System.currentTimeMillis();
        try {
            FileReader reader = new FileReader(file);
            StringBuffer stringBuffer = new StringBuffer();
            char[] chars = new char[12];
            while (reader.read(chars) != -1) {
                stringBuffer.append(chars);
            }
            reader.close();
            System.out.println(stringBuffer.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("使用BIO读取文件耗时：" + (System.currentTimeMillis() - startTime) + "毫秒");
        }
    }

    /**
     * 使用NIO读取文件
     */
    public static void nioReadFile() {

        try {
            RandomAccessFile randomAccessFile = new RandomAccessFile("number.txt", "rw");  //相当于 bio 中的  new file
            FileChannel inChannel = randomAccessFile.getChannel();  // 相当于 getInputStream

            ByteBuffer buf = ByteBuffer.allocate(10);

            int bytesRead = inChannel.read(buf); //read into buffer.  不对, it  should be wrote into buffer ;  buffer 是一块内存区域;
            int count = 0 ;
            System.out.println( "buf 的limit 是: " +   buf.limit()  + "  position 是: " + buf.position());
            while (bytesRead != -1) {

                buf.flip();  //make buffer ready for read ;  相当于重置了指针
                System.out.println("第" + count++  + "次处理") ;

                System.out.println( "buf 的limit 是: " +   buf.limit()  + "  position 是: " + buf.position());

                while (buf.hasRemaining()) {
                    System.out.print((char) buf.get()); // read 1 byte at a time
                }
                System.out.println();
                buf.clear();      //make buffer ready for writing  注意, clear 不是清空数据, 而是重置指针
                bytesRead = inChannel.read(buf);
                System.out.println( " read()  读取之后    buf 的limit 是: " +   buf.limit()  + "  position 是: " + buf.position());

            }
            randomAccessFile.close();
        } catch (Exception e) {

            e.printStackTrace();
        }

    }


    public static void inBuffer(String[] args) {

        IntBuffer buffer = IntBuffer.allocate(8);
        for (int i = 0; i < buffer.capacity(); i++) {
            int j = 2 * (i + 1);
            buffer.put(j);
        }

        buffer.flip();
        while (buffer.hasRemaining()) {


            int i = buffer.get();

            System.out.println(i);
        }


    }

    /**
     * 缓冲区分片
     */
    static public void bufferSlice(String args[]) {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        // 缓冲区中的数据0-9
        for (int i = 0; i < buffer.capacity(); ++i) {
            buffer.put((byte) i);
        }
        // 创建子缓冲区
        buffer.position(3);
        buffer.limit(7);
        ByteBuffer slice = buffer.slice();
        // 改变子缓冲区的内容
        for (int i = 0; i < slice.capacity(); ++i) {
            byte b = slice.get(i);
            b *= 10;
            slice.put(i, b);
        }
        buffer.position(0);
        buffer.limit(buffer.capacity());
        while (buffer.remaining() > 0) {
            System.out.println(buffer.get());
        }
    }


    public static void main1(String[] args) {
        //1 . 创建一个存储 Int 类型数据的 Buffer , 可以存储 1024 个字节
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        //2 . 向缓冲区中放入数据
        buffer.putInt(8888);
        buffer.putDouble(88.888);
        buffer.putShort((short) 888);

        //3 . 写入转读取前先翻转, 将 position 设置为 0
        buffer.flip();

        //4 . 将上述缓冲区转为只读缓冲区
        ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();

        //5 . 从缓冲区中读取数据
        int intValue = readOnlyBuffer.getInt();
        double doubleValue = readOnlyBuffer.getDouble();
        short shortValue = readOnlyBuffer.getShort();
        //已经读取完了, 在读取就溢出了 java.nio.BufferUnderflowException
        //buffer.getInt();
        //向只读缓冲区中存放数据抛 java.nio.ReadOnlyBufferException 异常
        //readOnlyBuffer.putShort((short) 888);

        //5 . 打印读取的数据信息
        System.out.println(String.format("intValue = %d, doubleValue = %f, shortValue = %d",
                intValue, doubleValue, shortValue));
    }


    public static void test() {
        ByteBuffer buffer = ByteBuffer.allocate(10);

        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte) i);
        }

        ByteBuffer readonlyBuffer = buffer.asReadOnlyBuffer();

        for (int j = 0; j < buffer.capacity(); j++) {
            int value = readonlyBuffer.get(j);
            System.out.print(value + " ");
        }
        System.out.println();

        // 重置buffer中的position=0,limit=capacity=10
        buffer.clear();

        // 修改源buffer中的内容
        for (int k = 0; k < buffer.capacity(); k++) {
            int va = k * 2;
            buffer.put((byte) va);
        }

        // 打印修改后的内容
        for (int j = 0; j < buffer.capacity(); j++) {
            int value = readonlyBuffer.get(j);
            System.out.print(value + " ");
        }
    }


    public static void main(String[] args) {
        //rwFile();
        //  bioReadFile();
         nioReadFile();


    }


}
